#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <math.h>
#include "pin.h"
#include <aos/kernel.h>
#include "ulog/ulog.h"
#include "aos/hal/uart.h"
#include "uart_packet.h"
#include "encrpyt.h"
#include "ipcm_function.h"
#include "ipcm.h"
#include "user_task/user_task.h"
#include "aos/kernel.h"
#include "userFaceSample.h"
#include "aos/kv.h"
#include "app_md5.h"
#include "faceproc.h"

#include "limoi-videoiva11-jpeg-decoder.h"
//#include "demo_ui.h"
//#include "cli_ai_para.h"

#include "if_v.h"

#define LOCK_ENABLE 1
#define TAG "UART-TASK:"
#define UART_PORT 1

#define FOR_SENSETIME_DEBUG_DATA  1

#if UART_TRANSFER_PIC_ENBALE
#define UART_RECV_BUF_SIZE 1024*100
#else
#define UART_RECV_BUF_SIZE 512
#endif

#define MODLE_VERSION_MAX_LEN 20

static uart_dev_t uart_ctrl;
uint8_t *uart_recv_buf = NULL;

struct AIE_FACE_MATCH_PARAM aie_face_match_param;
const uint8_t power_on_ready[9]={0xEF ,0xAA ,0x01 ,0x00 ,0x00 ,0x00 ,0x01 ,0x03 ,0x05};
const uint8_t cmd_err_ack[10]={0xEF ,0xAA ,0x00 ,0x00 ,0x00 ,0x00 ,0x02 ,0x00 ,0x01 ,0x03};

const uint8_t cmd_reset_ack[10]={0xEF ,0xAA ,0x00 ,0x00 ,0x02 ,0x10 ,0x00 ,0x12};
const uint8_t cmd_face_reset_ack[10]={0xEF ,0xAA ,0x00 ,0x00 ,0x02 ,0x23 ,0x00 ,0x25};

const uint8_t device_id[20]={0x43 ,0x4F ,0x42 ,0x41 ,0x31 ,0x33 ,0x38 ,0x39 ,0x30 ,0x31 ,0x32 ,0x34 ,0x30 ,0x37 ,0x38 ,0x39 ,0x33 ,0x32 ,0x31,0x30};
msg_pack_clear_t  msgPacket; 	


extern data_flow_func_control_t g_ifv_flow_cfg; 
extern uint8_t mipiWorkStatusFlag;

#define FOR_TEST 1
#if FOR_TEST
uint8_t g_user_name[USER_NAME_SIZE];
uint8_t version[VERSION_INFO_BUFFER_SIZE];


#endif
	
struct INNO_ICP_RECOG{
 uint8_t   result;
 int16_t   recognize_num;
 int16_t   recognize_id[5];
}inno_icp_recog;

uint32_t enroll_or_recognize_busy_flag = 0;
uint32_t enroll_from_uart_busy_flag = 0;

s_msg_enc_release_key_data  encreleasekey;
s_msg_enc_key_number_data enckeynumber;
s_msg_init_encryption_data encryption;

extern uint8_t  printf_hex;
extern int aie_vis_detect_enable;
extern uint8_t isp_rgb_enable_flag;

extern data_flow_func_control_t g_ifv_flow_cfg;

#define MSG_ENCRYT_KEY "encryt_key" 
#define MSG_ENCRYT_KEY_NUM "encryt_key_num"
#define MSG_ENCRYT_MODE "encryt_mode" 

void MsgGetVersionReply(uint8_t *version,uint8_t result);
void MsgNoDataReply(uint8_t cmd,uint8_t result);
void msg_get_status_reply(MsgID_e id,uint8_t result,uint8_t status);
void registerFromUartAck(uint32_t result,uint32_t id);
void saveFeatureAck(uint32_t result,uint32_t id);
void getCurrentRegisteredID(void);
void getModleVersionAck(char *detect, char *landmark ,char *recog);
void getEveryModelVersion(char *version, char *detect, char *landmark, char *recog);

extern int user_multi_angle_recog_sample_run(uint8_t timeout);
extern int m2h_request_id_ack(uart_dev_t *uart,uint32_t id);
extern char *TSM_ALGO_GetModelVersion(TsmHandle handle);

int msg_setValueKV(const char *key, const void *value, int len)
{
	int ret = -1;

	ret = aos_kv_set(key, (void *)value, len, 1);
	if(ret){
		printf("Failed to save %s. %d \n", key, ret);
	}
	
	return ret;
}


int msg_getValueKV(const char *key, void *buffer, int *buffer_len)
{
	int ret = -1;
	ret = aos_kv_get(key, buffer, buffer_len);
	if(ret){
		printf("Failed to load %s. %d \n", key, ret);
	}
	
	return ret;
}

uint8_t msg_check_sum(uint8_t *inbuf,uint8_t size)
{
	uint8_t  ncheck_sum = 0;
	uint8_t i = 0;

	for(i = 0; i < size; i++)   
	{
		ncheck_sum ^= inbuf[i];//XOR ALG
	}
 
	return ncheck_sum;
}

void msg_set_enc_key_reply(MsgID_e id,uint8_t result)
{
	s_msg_reply msg_reply;
    
	memset(&msg_reply,0,sizeof(s_msg_reply));
	msg_reply.msg_reply_head.sync_word[0] = (uint8_t)SYNC_WORD_FIRST;
	msg_reply.msg_reply_head.sync_word[1] = SYNC_WORD_SECOND;
	msg_reply.msg_reply_head.cmd = MID_REPLY;
	msg_reply.msg_reply_head.size[0] = 0x00;
	msg_reply.msg_reply_head.size[1] = 0x02;

	msg_reply.msg_reply_data.nid = id;
	msg_reply.msg_reply_data.result = result;
    msg_reply.msg_reply_data.data[0] = msg_check_sum(&msg_reply.msg_reply_head.cmd,MSG_REPLY_HEAD_SIZE-2);
	hal_uart_send(&uart_ctrl, &msg_reply, MSG_REPLY_HEAD_SIZE+1, 10);
}

void msg_set_init_encryption_reply(MsgID_e id,uint8_t result,uint8_t *device_id,uint8_t device_id_len)
{
	uint8_t tmp_msg[32];
	uint8_t tmp_msg_enc[32];
    s_msg_enc_reply msg_enc_reply;
	memset(tmp_msg,0,32);
	memset(tmp_msg_enc,0,32);
	tmp_msg[0] = MID_REPLY;
	tmp_msg[1] = 0x00;
	tmp_msg[2] = 0x16;
    tmp_msg[3] = id;
	tmp_msg[4] = result;
	memcpy(&tmp_msg[5],device_id,device_id_len);
	encBytes(tmp_msg,25,encreleasekey.enc_release_key,16,tmp_msg_enc);

    memset(&msg_enc_reply,0,sizeof(s_msg_enc_reply));

	msg_enc_reply.msg_enc_reply_head.sync_word[0] = (uint8_t)SYNC_WORD_FIRST;
	msg_enc_reply.msg_enc_reply_head.sync_word[1] = SYNC_WORD_SECOND;
	msg_enc_reply.msg_enc_reply_head.size[0] = 0x00;
	msg_enc_reply.msg_enc_reply_head.size[1] = 0x19;
	memcpy(&msg_enc_reply.msg_enc_reply_data.data[0],tmp_msg_enc,25);
	msg_enc_reply.msg_enc_reply_data.data[25] = msg_check_sum(msg_enc_reply.msg_enc_reply_data.data,25);
 
	hal_uart_send(&uart_ctrl, &msg_enc_reply,  30, 10);
}

void msg_send_result_reply(MsgID_e id,uint8_t result)
{
	s_msg_reply msg_reply;
    
	memset(&msg_reply,0,sizeof(s_msg_reply));
	msg_reply.msg_reply_head.sync_word[0] = (uint8_t)SYNC_WORD_FIRST;
	msg_reply.msg_reply_head.sync_word[1] = SYNC_WORD_SECOND;
	msg_reply.msg_reply_head.cmd = MID_REPLY;
	msg_reply.msg_reply_head.size[0] = 0x00;
	msg_reply.msg_reply_head.size[1] = 0x02;

	msg_reply.msg_reply_data.nid = id;
	msg_reply.msg_reply_data.result = result;
    msg_reply.msg_reply_data.data[0] = msg_check_sum(&msg_reply.msg_reply_head.cmd,MSG_REPLY_HEAD_SIZE-2);
	hal_uart_send(&uart_ctrl, &msg_reply, MSG_REPLY_HEAD_SIZE+1, 10);

}

void MsgNotifyBrokePeepholeReply()
{
	uint8_t m2h_data[10];
	m2h_data[0] = MID_NOTIFY_COULD_BROKE_PEEPHOLE;
	m2h_data[1] = 0;
	m2h_msg_send(&uart_ctrl, MID_REPLY, 2, m2h_data);
}

int handle_host_cmd(uint8_t *inbuf)
{
	int ret = 0;
	uint8_t msgid = inbuf[0];
	uint16_t id_16;
	int32_t id_32;
	ifv_msg_pkg_t msg;

	if(g_ifv_flow_cfg.sensetime_protocol_enable)
	{
		uint16_t msglen = 0;
		uint32_t  i = 0;
		// uint8_t  ncheck_sum = 0;
	
		memset(&msgPacket,0,sizeof(msg_pack_clear_t));

		if (( msgid == MID_INIT_ENCRYPTION ) || ( msgid == MID_SET_RELEASE_ENC_KEY ) || ( msgid == MID_SET_DEBUG_ENC_KEY )  || ( msgid == MID_POWERDOWN) || ( msgid == MID_DELALL )  )// unencrypted message
		{
			//step 1: checksum
			msglen = (inbuf[1] << 8) | inbuf[2];
			if(inbuf[1+2+msglen] != msg_check_sum(&inbuf[0],1+2+msglen))
			{
				ifv_printf(IFV_MSG_ERROR,"%s  checksum error! \n",__func__);
				return -1;
			}
			//step2: get mesage 
			memcpy(&msgPacket,&inbuf[0],1+2+msglen);
		}
		else if ( msgid == 0x00 ) //other sensetime msgid,encrypted message
		{
			//step 1: checksum
			msglen = (inbuf[0] << 8) | inbuf[1];
			if(inbuf[2+msglen] != msg_check_sum(&inbuf[2],msglen))
			{
				ifv_printf(IFV_MSG_ERROR,"%s  checksum error! \n",__func__);
				return -1;
			}

			//step 2: descpryt message.
			decBytes(&inbuf[2],msglen,encreleasekey.enc_release_key,16,(uint8_t *)&msgPacket);
		}
		ifv_printf(IFV_MSG_INFO,"MSG ID:0x%02x\n",msgPacket.MsgID);
		switch(msgPacket.MsgID)
		{
			case MID_INIT_ENCRYPTION:
				memcpy(&encryption,msgPacket.Data,sizeof(encryption));
				uint8_t key_md5[16] = "0";
				uint8_t str_md5[32] = "0";
				md5_main(encryption.seed,key_md5,sizeof(encryption.seed));
				md5_HexDevide2DoubleHex( str_md5, key_md5,16);
				memset(encreleasekey.enc_release_key,0,16);

				for(i=0;i<16;i++)
				{
					encreleasekey.enc_release_key[i] = str_md5[enckeynumber.enc_key_number[i]];
					if((0x0a<=encreleasekey.enc_release_key[i] && encreleasekey.enc_release_key[i]<=0x0f) || (0x0A<=encreleasekey.enc_release_key[i] && encreleasekey.enc_release_key[i]<=0x0F) )//|| ('a'<=debug_key[i] && debug_key[i]<='f') || ('A'<=debug_key[i] && debug_key[i]<='Z'))
					{
						encreleasekey.enc_release_key[i] = encreleasekey.enc_release_key[i] + 0x57;
					}
					else if(0x00<=encreleasekey.enc_release_key[i] && encreleasekey.enc_release_key[i]<=0x09)
					{
						encreleasekey.enc_release_key[i] = encreleasekey.enc_release_key[i] + 0x30;
					}
				}
				msg_setValueKV(MSG_ENCRYT_MODE, &encryption.mode, 1);
				msg_setValueKV(MSG_ENCRYT_KEY, encreleasekey.enc_release_key, 16);
				ifv_printf(IFV_MSG_DEBUG,"KEY: ");
				for(int i =0; i<16;i++)
				{
					ifv_printf(IFV_MSG_DEBUG,"%02x ",encreleasekey.enc_release_key[i]);
				}
				ifv_printf(IFV_MSG_DEBUG,"\n");
				ifv_printf(IFV_MSG_DEBUG,"Mode: %d\n",encryption.mode);
				msg_set_init_encryption_reply(MID_INIT_ENCRYPTION,0,(uint8_t *)device_id,20);
			break;
			case MID_SET_RELEASE_ENC_KEY:
				memcpy(&enckeynumber.enc_key_number[0],msgPacket.Data,16);
				msg_setValueKV(MSG_ENCRYT_KEY_NUM, enckeynumber.enc_key_number, 16);
				msg_set_enc_key_reply(MID_SET_RELEASE_ENC_KEY,0);
				ifv_printf(IFV_MSG_DEBUG,"RELEASE KEY_NUMBER: ");
				for(int i =0; i<16;i++)
				{
					ifv_printf(IFV_MSG_DEBUG,"%02x ",enckeynumber.enc_key_number[i]);
				}
				ifv_printf(IFV_MSG_DEBUG,"\n");
			break;
			case MID_SET_DEBUG_ENC_KEY:
				memcpy(&enckeynumber.enc_key_number[0],msgPacket.Data,16);
				msg_setValueKV(MSG_ENCRYT_KEY_NUM, enckeynumber.enc_key_number, 16);
				msg_set_enc_key_reply(MID_SET_DEBUG_ENC_KEY,0);
				ifv_printf(IFV_MSG_DEBUG,"DEBUG KEY_NUMBER: ");
				for(int i =0; i<16;i++)
				{
					ifv_printf(IFV_MSG_DEBUG,"%02x ",enckeynumber.enc_key_number[i]);
				}
				ifv_printf(IFV_MSG_DEBUG,"\n");
			break;
			
			case MID_GET_VERSION: 
				ifv_printf(IFV_MSG_INFO,"get soft version \n");
				MsgGetVersionReply((uint8_t *)RELEASE_SOFT_VERSION,MR_SUCCESS);
			break;
			case MID_DEBUG_MODE: 
				MsgNoDataReply(MID_DEBUG_MODE,MR_SUCCESS);
			break;
			case MID_GET_DEBUG_INFO:
			break;
			case MID_UPLOAD_DEBUG_INFO: 
			break;
			case MID_RESET:
				if(0 == user_multi_angle_reg_stop())
					MsgNoDataReply(MID_FACERESET,MR_SUCCESS);
			break;
			case MID_POWERDOWN:
				aos_msleep(5);
				MsgNoDataReply(MID_POWERDOWN,MR_SUCCESS);
			break;
			case MID_GETSTATUS:
				msg_get_status_reply(MID_GETSTATUS,MR_SUCCESS,ifvGetFlowState());
			break;
			case MID_VERIFY:  
				if(0 == enroll_or_recognize_busy_flag)
				{
					enroll_or_recognize_busy_flag = 1;
					enroll_from_uart_busy_flag = 0;
					ifv_printf(IFV_MSG_INFO,"%s cmd recongnize \n",__func__);

					s_msg_verify_data *verify_data = (s_msg_verify_data *)msgPacket.Data;
					ret = user_multi_angle_recog_sample_run(verify_data->timeout);
					if(ret)
						enroll_or_recognize_busy_flag = 0;
				}
			break;
			case MID_ENROLL:   	// to enroll and register the persion in front of the camera
				if(0 == enroll_or_recognize_busy_flag)
				{
					s_msg_enroll_data *enroll_data = (s_msg_enroll_data *)msgPacket.Data;
					enroll_or_recognize_busy_flag = 1;
					enroll_from_uart_busy_flag = 0;
					ifv_printf(IFV_MSG_INFO,"%s cmd register \n",__func__);
					ifv_printf(IFV_MSG_DEBUG,"Enroll username:");
					for(i = 0;i <32; i++)
					{
						ifv_printf(IFV_MSG_DEBUG,"%02x ",enroll_data->user_name[i]);
					} 
					ifv_printf(IFV_MSG_DEBUG,"\n");
					ifv_printf(IFV_MSG_DEBUG,"Enroll admin:%d, direction:%d, timeout:%d\n",enroll_data->admin, enroll_data->face_direction, enroll_data->timeout);

					ret = user_multi_angle_reg_sample_run(enroll_data->admin, enroll_data->user_name, enroll_data->face_direction, enroll_data->timeout, 0xFFFF);
					if(ret)
						enroll_or_recognize_busy_flag = 0;
				}
			break;
			case MID_ENROLL_COVER: 
				if(0 == enroll_or_recognize_busy_flag)
				{
					s_msg_enroll_cover_data *enroll_cover_data = (s_msg_enroll_cover_data *)msgPacket.Data;
					enroll_or_recognize_busy_flag = 1;
					enroll_from_uart_busy_flag = 0;
					ifv_printf(IFV_MSG_INFO,"%s cmd register \n",__func__);
					ifv_printf(IFV_MSG_DEBUG,"Enroll cover username:");
					for(i = 0;i <32; i++)
					{
						ifv_printf(IFV_MSG_DEBUG,"%02x ",enroll_cover_data->user_name[i]);
					}
					ifv_printf(IFV_MSG_DEBUG,"\n");
					ifv_printf(IFV_MSG_DEBUG,"Enroll cover admin:%d, direction:%d, timeout:%d, user_id:%d \n",enroll_cover_data->admin, enroll_cover_data->face_direction, enroll_cover_data->timeout, enroll_cover_data->user_id);
					ret = user_multi_angle_reg_sample_run(enroll_cover_data->admin, enroll_cover_data->user_name, enroll_cover_data->face_direction, enroll_cover_data->timeout, enroll_cover_data->user_id);
					if(ret)
						enroll_or_recognize_busy_flag = 0;
				}
			break;
			case MID_FACERESET:
				if(0 == user_multi_angle_reg_stop())
					MsgNoDataReply(MID_FACERESET,MR_SUCCESS);
			break;
			case MID_DELUSER:
			{
				dump_le_uint16(msgPacket.Data, &id_16);
				LOGI(TAG, "DEL FACE ID=%d \n",id_16);
				
				msg.cmd = APP2IFV_DEL_USER_CMD;
				msg.value = id_16;
				ifv_post_msg(msg);
			}
			break;
			case MID_DELUSER_RANG:
			{			
				// s_msg_deluser_rang_data *deluser_rang = (s_msg_deluser_rang_data *)msgPacket.Data;
				//printf("[Dennis]->deluser_rang from:%d\n",deluser_rang->user_id_from);
				//printf("[Dennis]->deluser_rang to:%d\n",deluser_rang->user_id_to);
					
				msg.cmd = APP2IFV_DEL_USER_RANGE_CMD;
				msg.pData = msgPacket.Data;
				ifv_post_msg(msg);
			}
			break;
			case MID_DELALL:
				msg.cmd = APP2IFV_DEL_ALL_USERS_CMD;
				ifv_post_msg(msg);
			break;
			case MID_GETUSERINFO:
				dump_le_uint16(msgPacket.Data, &id_16);
				LOGI(TAG, "Get FACE ID=%d \n",id_16);
			
				msg.cmd = APP2IFV_GET_USER_INFO_CMD;
				msg.value = id_16;
				ifv_post_msg(msg);	
			break;
			case MID_GETALLUSERID:
				msg.cmd = APP2IFV_GET_ALL_USERS_ID_CMD;
				ifv_post_msg(msg);
			break;
			case MID_CONFIG_BAUDRATE: 
			break;
			case MID_SET_THRESHOLD_LEVEL:
				msg.cmd = APP2IFV_SET_THRESH_CMD;
				msg.pData = msgPacket.Data;
				ifv_post_msg(msg);
			break;
			case MID_DEMOMODE:
				if(0 == enroll_or_recognize_busy_flag)
				{
					enroll_or_recognize_busy_flag = 1;
					enroll_from_uart_busy_flag = 0;
					ifv_printf(IFV_MSG_INFO,"%s cmd demo mode \n",__func__);

					g_ifv_flow_cfg.mid_debug_mode_flag = 1;
					ret = user_multi_angle_recog_sample_run(0);
					if(ret){
						MsgNoDataReply(MID_DEMOMODE,MR_REJECTED);
						g_ifv_flow_cfg.mid_debug_mode_flag = 0;
						enroll_or_recognize_busy_flag = 0;
					}else{
						MsgNoDataReply(MID_DEMOMODE,MR_SUCCESS);
					}
				}
				break;
			default:
				msg_send_result_reply(msgPacket.MsgID,MR_REJECTED);
				ifv_printf(IFV_MSG_WARNING,"unknown command!~\n");
			break;
		}
	}
	else
	{
		uint32_t size = 0;
		dump_le_uint32(&inbuf[1], &size);	
#if 0
		//ack mcu
		{
			uint8_t m2h_data_ack[2];
			m2h_data_ack[0] = MID_REPLY;
			m2h_data_ack[1] = MR_SUCCESS;
			m2h_msg_send(&uart_ctrl, MID_REPLY, 2, m2h_data_ack); 
		}	
#endif

		ifv_printf(IFV_MSG_INFO,"MSG ID:0x%02x\n",msgid);	
		switch(msgid)
		{
			// Host to Module (h->m)
			case MID_RESET:		// stop and clear all in-processing messages. enter standby mode
				break; 
			case MID_GETSTATUS: // to ping the module and get the status	
			{
				s_msg_reply_getstatus_data status_data;
				status_data.status = MS_STANDBY; // IDLE, waiting for commands
				uint8_t m2h_data[3];
				m2h_data[0] = MID_GETSTATUS;
				m2h_data[1] = MR_SUCCESS;
				m2h_data[2] = status_data.status;
				m2h_msg_send(&uart_ctrl, MID_REPLY, 3, m2h_data); 
				break; 
			}
			case MID_VERIFY:    // to verify the person in front of the camera	
				if(0 == enroll_or_recognize_busy_flag)
				{
					enroll_or_recognize_busy_flag = 1;
					enroll_from_uart_busy_flag = 0;
					printf("%s cmd recongnize \n",__func__);
					msg.cmd = APP2IFV_RECOGNIZE_CMD;
					ifv_post_msg(msg);
				}

				break;
			case MID_ENROLL:   	// to enroll and register the persion in front of the camera
				if(0 == enroll_or_recognize_busy_flag)
				{
					enroll_or_recognize_busy_flag = 1;
					enroll_from_uart_busy_flag = 0;
					printf("%s cmd register \n",__func__);
					msg.cmd = APP2IFV_REGISTER_CMD;
					ifv_post_msg(msg);
				}
				break;
			case MID_ENROLL_UART:
				if(0 == enroll_or_recognize_busy_flag)
				{
					enroll_or_recognize_busy_flag = 1;
					enroll_from_uart_busy_flag = 1;
					printf("%s cmd register : pic from uart \n",__func__);
					int ret = 0;
					ret = jpeg_to_raw((char *)&inbuf[H2M_PACKET_HEADER_LEN],size, (char *)MM_IMG_RGB_FROM_UART,NULL,NULL,EXT_RGBA);
					if (0 == ret){
						printf("image convert done \n");
						msg.cmd = APP2IFV_REGISTER_UART_CMD;
						ifv_post_msg(msg);
					}
					else{
						printf("image convert failed! \n");
						enroll_or_recognize_busy_flag = 0;
						enroll_from_uart_busy_flag = 0;
						registerFromUartAck(1,0xffffffff);
					}	
				}
				break;
			case MID_SAVE_FEARURE_UART:
				if(0 == enroll_or_recognize_busy_flag)
				{
					id_32 = tsm_ff_add(&inbuf[H2M_PACKET_HEADER_LEN], NULL);
					if(id_32 >= 0)
						saveFeatureAck(0, id_32);
					else
						saveFeatureAck(0x0a, 0xffffffff);
				}
				break;
			case MID_SNAPIMAGE: // to snap a picture and save it
				{
					printf("snap a picture  \n");
					uint8_t msg_type = inbuf[4];
					if(msg_type == 0x1)
						msg.cmd = APP2IFV_SNAP_IR_CMD;
					else if(msg_type == 0x2)
						msg.cmd = APP2IFV_SNAP_SPK_CMD;
					ifv_post_msg(msg);
				}
				break;
			case MID_GETSAVEDIMAGE: // to get size of saved image
				break;
			case MID_UPLOADIMAGE:   // upload images
				break; 
			case MID_DELUSER:   // Delete the specified user with user id
			{
				uint16_t id_16;
				dump_le_uint16(&inbuf[5], &id_16);
				LOGI(TAG, "DEL FACE ID=%d \n",id_16);
			
				msg.cmd = APP2IFV_DEL_USER_CMD;
				msg.value = id_16;
				ifv_post_msg(msg);
			}
				break;
			case MID_DELALL:   	// Delete all registerred users
				msg.cmd = APP2IFV_DEL_ALL_USERS_CMD;
				ifv_post_msg(msg);
				break;
			case MID_GETUSERINFO:   // Get user info		
				break;
			case MID_FACERESET:     // Reset face status
				break;
			case DRAW_RECT:  // 
				break;
			case MID_GET_MODLE_VERSION:
				{
					char detectV[20] = {0};
					char landmarkV[20] = {0};
					char recogV[20] = {0};
					char *version = (char *)TSM_ALGO_GetModelVersion(NULL);
					printf("modle version:%s\n", version);
					getEveryModelVersion(version, detectV, landmarkV, recogV);
					getModleVersionAck(detectV, landmarkV, recogV);
				}
				break;
			case MID_GET_VERSION:   // get version information
			break;

			case MID_WRITE_SN:      // write sn to board
			break;

			case MID_START_OTA:     // ask the module to enter OTA mode
			break;

			case MID_STOP_OTA:      // ask the module to exit OTA mode
			break;

			case MID_GET_OTA_STATUS: // query the current ota status
			break;

			case MID_OTA_HEADER:    // the ota header data
			break;

			case MID_OTA_PACKET:    // the data packet, carries real firmware data
			break;

			case MID_INIT_ENCRYPTION: // initialize encrypted communication
			break;

			case MID_CONFIG_BAUDRATE: // config uart baudrate
			break;

			case MID_SET_RELEASE_ENC_KEY: // set release encrypted key(Warning!!!:Once set, the KEY will not be able to modify)

			break;
			case MID_SET_DEBUG_ENC_KEY: // set debug encrypted key
			break;

			case MID_GET_LOGFILE: 		// get log file
			break;

			case MID_UPLOAD_LOGFILE: 	// upload log file
			break;
			case MID_ISP_START_SET:
				msg.cmd = APP2IFV_ISP_START_SET;
				ifv_post_msg(msg);
				break;
			case MID_ISP_STOP_SET:
				msg.cmd = APP2IFV_ISP_STOP_SET;
				ifv_post_msg(msg);
				break;
			case MID_RECT_COLOUR_SET:
				break;		
			case MID_FACTORY_TEST:  	// factory test
			break;

			case MID_CONTINUE_RECOGNIZE:      	// 		
			break;

			case MID_SET_THRESHOLD_LEVEL: // Set threshold level
			break;

			case MID_POWERDOWN: 		// be prepared to power off
			break;

			case MID_DEBUG_MODE:
			break;

			case MID_GET_DEBUG_INFO:    // get size of debug information
			break;

			case MID_UPLOAD_DEBUG_INFO: // upload debug information
			break;

			case MID_DEMOMODE:  		// enter demo mode, verify flow will skip feature comparation step.
		
				break;
			case MI2_PC2MCU_REQUEST_ID :
				if(0 == enroll_or_recognize_busy_flag)	
				{
					printf("pc request current id \n");
					getCurrentRegisteredID();
				}
				else
				{
					printf("tx510 process register ... \n");
				}
			
				break;
			case MID_MAX:       		// reserved
				printf_hex = inbuf[3];
				if(printf_hex == 0)
				{
					aos_set_log_level(AOS_LL_INFO);
					printf("ascii mode\r\n");
				}
				else if(printf_hex == 1)
				{
					aos_set_log_level(AOS_LL_WARN);
					printf("hex mode\r\n");
				}
				else
				{
					printf_hex = 1;
					printf("cmd error, default hex mode!\n");
				}
				break;
			case MID_NOTIFY_COULD_BROKE_PEEPHOLE:
				mipiWorkStatusFlag |= 1 << 1;
				printf("notify could broke peephole\n");
				MsgNotifyBrokePeepholeReply();
				break;
			default:
				break;
		}
	}
 
	return 0;
}

#include "drv_usart.h"
#include "drv_uart.h"
static uint32_t curRegisteredID = 0;

void systemReadyNoteMsg(void)
{
	s_msg_note msg_note;
    
	memset(&msg_note,0,sizeof(s_msg_note));
	msg_note.note_head.sync_word[0] = (uint8_t)SYNC_WORD_FIRST;
	msg_note.note_head.sync_word[1] = SYNC_WORD_SECOND;
	msg_note.note_head.cmd = MID_NOTE;
	msg_note.note_head.size[0] = 0x00;
	msg_note.note_head.size[1] = 0x01;

	msg_note.note_data.nid = NID_READY;
    msg_note.note_data.checksum = msg_check_sum(&msg_note.note_head.cmd,sizeof(msg_note)-1);
	hal_uart_send(&uart_ctrl, &msg_note, sizeof(msg_note), 10);
}

void systemUnknowErrorNoteMsg(void)
{
	s_msg_note msg_note;
    
	memset(&msg_note,0,sizeof(s_msg_note));
	msg_note.note_head.sync_word[0] = (uint8_t)SYNC_WORD_FIRST;
	msg_note.note_head.sync_word[1] = SYNC_WORD_SECOND;
	msg_note.note_head.cmd = MID_NOTE;
	msg_note.note_head.size[0] = 0x00;
	msg_note.note_head.size[1] = 0x01;

	msg_note.note_data.nid = NID_UNKNOWNERROR;
    msg_note.note_data.checksum = msg_check_sum(&msg_note.note_head.cmd,sizeof(msg_note)-1);
	hal_uart_send(&uart_ctrl, &msg_note, sizeof(msg_note), 10);
}

void msg_get_status_reply(MsgID_e id,uint8_t result,uint8_t status)
{
	uint8_t tmp_msg[32];
	uint8_t tmp_msg_enc[32];
	uint8_t checksum = 0;

	memset(tmp_msg,0,32);
	memset(tmp_msg_enc,0,32);
	
	tmp_msg[0] = MID_REPLY;
	tmp_msg[1] = 0x00;
	tmp_msg[2] = 0x03;
    tmp_msg[3] = id;
	tmp_msg[4] = result;
	tmp_msg[5] = status;
#if FOR_SENSETIME_DEBUG_DATA
	memcpy(tmp_msg_enc,tmp_msg,6);
#else
	encBytes(tmp_msg,6,encreleasekey.enc_release_key,16,tmp_msg_enc);
#endif

	checksum = msg_check_sum(tmp_msg_enc,6);

    memset(tmp_msg,0,32);

	tmp_msg[0] = (uint8_t)SYNC_WORD_FIRST;
	tmp_msg[1] = SYNC_WORD_SECOND;
	tmp_msg[2] = 0x00;
	tmp_msg[3] = 0x06;
	memcpy(&tmp_msg[4],tmp_msg_enc,6);
	tmp_msg[4+6]  = checksum; 
  	ifv_printf(IFV_MSG_DEBUG,"%s: \n",__func__);
	for(int i = 0; i< 11;i++)
	{
		printf("0x%02x,",tmp_msg[i]);
	}
	printf("\n");
	hal_uart_send(&uart_ctrl, &tmp_msg,  11, 10);
}


void MsgNoteFace(uint8_t cmd,uint16_t status,int16_t left,int16_t top,int16_t right,int16_t bottom,int16_t yaw,int16_t pitch,int16_t roll)
{
	s_msg_note_face_t note;
	uint8_t tmp_msg_enc[64];
	uint8_t msg_verify_buf[64];
	uint8_t checksum = 0;

	memset(&note,0,sizeof(s_msg_note_face_t));
	memset(tmp_msg_enc,0,64);
	memset(msg_verify_buf,0,64); 
    //step 1: struct msg & encrypt
	note.MsgID = MID_NOTE;

	ifv_printf(IFV_MSG_DEBUG,"%s \n",__func__);
	ifv_printf(IFV_MSG_DEBUG,"size:%d, mid:0x%02x, state:%d \n",(1+sizeof(s_note_data_face)), cmd, status);
	ifv_printf(IFV_MSG_DEBUG,"left:0x%02x, right:0x%02x, top:0x%02x, bottom:0x%02x, yaw:0x%02x, pitch:0x%02x, roll:0x%02x \n",left,right,top,bottom,yaw,pitch,roll);
	note.Size[0] = ((1+sizeof(s_note_data_face)) >> 8) & 0xff;
	note.Size[1] = (1+sizeof(s_note_data_face)) & 0xff;
	note.mid = cmd;
	note.face.state = ((status << 8 )& 0xFF00) | ((status >> 8) &0x00FF);
	note.face.left = ((left << 8 )& 0xFF00) | ((left >> 8) &0x00FF);
	note.face.right = ((right << 8 )& 0xFF00) | ((right >> 8) &0x00FF);
	note.face.top = ((top << 8 )& 0xFF00) | ((top >> 8) &0x00FF);
	note.face.bottom = ((bottom << 8 )& 0xFF00) | ((bottom >> 8) &0x00FF);
	note.face.yaw = ((yaw << 8 )& 0xFF00) | ((yaw >> 8) &0x00FF);
	note.face.pitch = ((pitch << 8 )& 0xFF00) | ((pitch >> 8) &0x00FF);
	note.face.roll = ((roll << 8 )& 0xFF00) | ((roll >> 8) &0x00FF);
#if FOR_SENSETIME_DEBUG_DATA
	memcpy(tmp_msg_enc,&note,sizeof(s_msg_note_face_t));
#else
	encBytes(&note,sizeof(s_msg_note_face_t),encreleasekey.enc_release_key,16,tmp_msg_enc);
#endif

	checksum = msg_check_sum(tmp_msg_enc,sizeof(s_msg_note_face_t));

	//step 2: struct enroll reply msg
	msg_verify_buf[0] = (uint8_t)SYNC_WORD_FIRST;
	msg_verify_buf[1] = SYNC_WORD_SECOND;
	msg_verify_buf[2] = (sizeof(s_msg_note_face_t) >> 8) & 0xFF;
	msg_verify_buf[3] = (sizeof(s_msg_note_face_t)) & 0xFF;
	memcpy(&msg_verify_buf[4],tmp_msg_enc,sizeof(s_msg_note_face_t));
	msg_verify_buf[4+sizeof(s_msg_note_face_t)]  = checksum;
 	ifv_printf(IFV_MSG_DEBUG,"%s:",__func__);
	for(int i = 0; i< 1+4+sizeof(s_msg_note_face_t);i++)
	{
		ifv_printf(IFV_MSG_DEBUG,"0x%02x,",msg_verify_buf[i]);
	}
	ifv_printf(IFV_MSG_DEBUG,"\n");
	hal_uart_send(&uart_ctrl, &msg_verify_buf,  1+4+sizeof(s_msg_note_face_t), 10);
}


void MsgEnrollReply(uint8_t cmd,uint8_t result,uint16_t user_id, uint8_t direction) 
{
	s_msg_enroll_reply_t enroll;
	uint8_t tmp_msg_enc[64];
	uint8_t msg_verify_buf[64];
	uint8_t checksum = 0;
	memset(&enroll,0,sizeof(s_msg_enroll_reply_t));
	memset(tmp_msg_enc,0,64);
	memset(msg_verify_buf,0,64); 
    //step 1: struct msg & encrypt
	enroll.MsgID = MID_REPLY;
	enroll.Size[0] = ((2+sizeof(s_msg_reply_enroll_data)) >> 8) & 0xff;
	enroll.Size[1] = (2+sizeof(s_msg_reply_enroll_data)) & 0xff;
	enroll.mid = cmd;
	enroll.result = result;
	enroll.data.face_direction = direction;
	enroll.data.user_id_heb = (user_id >> 8) & 0xFF;
	enroll.data.user_id_leb = (user_id) & 0xFF;
#if FOR_SENSETIME_DEBUG_DATA
	memcpy(tmp_msg_enc,(uint8_t *)&enroll,sizeof(s_msg_enroll_reply_t));
#else
	encBytes((uint8_t *)&enroll,sizeof(s_msg_enroll_reply_t),encreleasekey.enc_release_key,16,tmp_msg_enc);
#endif
	checksum = msg_check_sum(tmp_msg_enc,sizeof(s_msg_enroll_reply_t));
     //step 2: struct enroll reply msg
	msg_verify_buf[0] = (uint8_t)SYNC_WORD_FIRST;
	msg_verify_buf[1] = SYNC_WORD_SECOND;
	msg_verify_buf[2] = (sizeof(s_msg_enroll_reply_t) >> 8) & 0xFF;
	msg_verify_buf[3] = (sizeof(s_msg_enroll_reply_t)) & 0xFF;
	memcpy(&msg_verify_buf[4],tmp_msg_enc,sizeof(s_msg_enroll_reply_t));
	msg_verify_buf[4+sizeof(s_msg_enroll_reply_t)]  = checksum;

 	ifv_printf(IFV_MSG_DEBUG, "%s:cmd:0x%02x, result: %d, user id 0x%02x, direction 0x%02x\n", __func__, cmd, result, user_id, direction);
	for(int i = 0; i<1+4+sizeof(s_msg_enroll_reply_t);i++)
	{
		ifv_printf(IFV_MSG_DEBUG,"0x%02x,",msg_verify_buf[i]);
	}
	ifv_printf(IFV_MSG_DEBUG,"\n");
	hal_uart_send(&uart_ctrl, &msg_verify_buf,  1+4+sizeof(s_msg_enroll_reply_t), 10);
}


void MsgVeifyUnSuccessReply(uint8_t result)
{
	s_msg_verify_reply_t verify;
	uint8_t tmp_msg_enc[64];
	uint8_t msg_verify_buf[64];
	uint8_t checksum = 0;
	memset(&verify,0,sizeof(s_msg_verify_reply_t));
	memset(tmp_msg_enc,0,64);
	memset(msg_verify_buf,0,64); 
    //step 1: struct msg & encrypt
	verify.MsgID = MID_REPLY;
	verify.Size[0] = 0;
	verify.Size[1] = 2;
	verify.mid = MID_VERIFY;
	verify.result = result;
#if FOR_SENSETIME_DEBUG_DATA
	memcpy(tmp_msg_enc,(uint8_t *)&verify,5);
#else
	encBytes((uint8_t *)&verify,5,encreleasekey.enc_release_key,16,tmp_msg_enc);
#endif
	checksum = msg_check_sum(tmp_msg_enc,5);
 
    //step 2: struct verify reply msg
	msg_verify_buf[0] = (uint8_t)SYNC_WORD_FIRST;
	msg_verify_buf[1] = SYNC_WORD_SECOND;
	msg_verify_buf[2] = 0;
	msg_verify_buf[3] = 5;
	memcpy(&msg_verify_buf[4],tmp_msg_enc,5);
	msg_verify_buf[4+5]  = checksum;
 	ifv_printf(IFV_MSG_DEBUG,"%s: result:0x%02x\n",__func__, result);
	for(int i = 0; i< 1+4+5;i++)
	{
		ifv_printf(IFV_MSG_DEBUG,"0x%02x,",msg_verify_buf[i]);
	}
	ifv_printf(IFV_MSG_DEBUG,"\n");
	hal_uart_send(&uart_ctrl, &msg_verify_buf,  1+4+5, 10);	
}

void MsgVeifyReply(uint8_t result,uint16_t user_id,uint8_t* user_name,uint8_t admin, uint8_t unlock_status)
{
	s_msg_verify_reply_t verify;
	uint8_t tmp_msg_enc[64];
	uint8_t msg_verify_buf[64];
	uint8_t checksum = 0;
	memset(&verify,0,sizeof(s_msg_verify_reply_t));
	memset(tmp_msg_enc,0,64);
	memset(msg_verify_buf,0,64); 
    //step 1: struct msg & encrypt
	verify.MsgID = MID_REPLY;
	verify.Size[0] = (sizeof(s_msg_reply_verify_data) >> 8) & 0xff;
	verify.Size[1] = sizeof(s_msg_reply_verify_data) & 0xff;
	verify.mid = MID_VERIFY;
	verify.result = result;
	verify.data.admin = admin;
	verify.data.unlockStatus =unlock_status;
	verify.data.user_id_heb = (user_id >> 8) & 0xFF;
	verify.data.user_id_leb = (user_id) & 0xFF;
	memcpy(verify.data.user_name,user_name,USER_NAME_SIZE);
#if FOR_SENSETIME_DEBUG_DATA
	memcpy(tmp_msg_enc,&verify,sizeof(s_msg_verify_reply_t));
#else
	encBytes(&verify,sizeof(s_msg_verify_reply_t),encreleasekey.enc_release_key,16,tmp_msg_enc);
#endif

	checksum = msg_check_sum(tmp_msg_enc,sizeof(s_msg_verify_reply_t));
 
    //step 2: struct verify reply msg
	msg_verify_buf[0] = (uint8_t)SYNC_WORD_FIRST;
	msg_verify_buf[1] = SYNC_WORD_SECOND;
	msg_verify_buf[2] = (sizeof(s_msg_verify_reply_t) >> 8) & 0xFF;
	msg_verify_buf[3] = (sizeof(s_msg_verify_reply_t)) & 0xFF;
	memcpy(&msg_verify_buf[4],tmp_msg_enc,sizeof(s_msg_verify_reply_t));
	msg_verify_buf[4+sizeof(s_msg_verify_reply_t)]  = checksum;
 	ifv_printf(IFV_MSG_DEBUG,"%s:", __func__);
	for(int i = 0; i< 1+4+sizeof(s_msg_verify_reply_t);i++)
	{
		ifv_printf(IFV_MSG_DEBUG,"0x%02x,",msg_verify_buf[i]);
	}
	ifv_printf(IFV_MSG_DEBUG,"\n");
	hal_uart_send(&uart_ctrl, &msg_verify_buf,  1+4+sizeof(s_msg_verify_reply_t), 10);	
}

void MsgNoDataReply(uint8_t cmd,uint8_t result)
{
	uint8_t tmp_msg_enc[64];
	uint8_t msg_buf[64];
	uint8_t checksum = 0;

	memset(msg_buf,0,64);
	memset(tmp_msg_enc,0,64);
	//step 1: struct msg & encrypt
	msg_buf[0] = MID_REPLY;
	msg_buf[1] = 0;
	msg_buf[2] = 2;
	msg_buf[3] = cmd;
	msg_buf[4] = result;
#if FOR_SENSETIME_DEBUG_DATA
	memcpy(tmp_msg_enc,&msg_buf,5);
#else
	encBytes(&msg_buf,5,encreleasekey.enc_release_key,16,tmp_msg_enc);
#endif
	checksum = msg_check_sum(tmp_msg_enc,5);

    //step 2: struct  reply msg
    memset(msg_buf,0,64);
	msg_buf[0] = (uint8_t)SYNC_WORD_FIRST;
	msg_buf[1] = SYNC_WORD_SECOND;
	msg_buf[2] = 0;
	msg_buf[3] = 5;
	memcpy(&msg_buf[4],tmp_msg_enc,5);
	msg_buf[4+5]  = checksum;
  	ifv_printf(IFV_MSG_DEBUG,"%s:", __func__);
	for(int i = 0; i< 1+4+5;i++)
	{
		ifv_printf(IFV_MSG_DEBUG,"0x%02x,",msg_buf[i]);
	}
	ifv_printf(IFV_MSG_DEBUG,"\n");
	hal_uart_send(&uart_ctrl, &msg_buf,  1+4+5, 10);		
}

void MsgGetVersionReply(uint8_t *version,uint8_t result)
{
	s_msg_version_t ver;
	uint8_t tmp_msg_enc[64];
	uint8_t msg_verify_buf[64];
	uint8_t checksum = 0;
	memset(&ver,0,sizeof(s_msg_version_t));
	memset(tmp_msg_enc,0,64);
	memset(msg_verify_buf,0,64); 
    //step 1: struct msg & encrypt
	ver.MsgID = MID_REPLY;
	ver.Size[0] = (sizeof(s_msg_version_t) >> 8) & 0xff;
	ver.Size[1] = sizeof(s_msg_version_t) & 0xff;
	ver.mid = MID_GET_VERSION;
	ver.result = result;
	memcpy(ver.data.version_info,version,VERSION_INFO_BUFFER_SIZE);

#if FOR_SENSETIME_DEBUG_DATA
	memcpy(tmp_msg_enc,&ver,sizeof(s_msg_version_t));
#else
	encBytes(&ver,sizeof(s_msg_version_t),encreleasekey.enc_release_key,16,tmp_msg_enc);
#endif
	checksum = msg_check_sum(tmp_msg_enc,sizeof(s_msg_version_t));
 
    //step 2: struct verify reply msg
	msg_verify_buf[0] = (uint8_t)SYNC_WORD_FIRST;
	msg_verify_buf[1] = SYNC_WORD_SECOND;
	msg_verify_buf[2] = (sizeof(s_msg_version_t) >> 8) & 0xFF;
	msg_verify_buf[3] = (sizeof(s_msg_version_t)) & 0xFF;
	memcpy(&msg_verify_buf[4],tmp_msg_enc,sizeof(s_msg_version_t));
	msg_verify_buf[4+sizeof(s_msg_version_t)]  = checksum;
   	ifv_printf(IFV_MSG_DEBUG,"%s:", __func__);
	for(int i = 0; i< 1+4+sizeof(s_msg_version_t);i++)
	{
		ifv_printf(IFV_MSG_DEBUG,"0x%02x,",msg_verify_buf[i]);
	}
	ifv_printf(IFV_MSG_DEBUG,"\n");
	hal_uart_send(&uart_ctrl, &msg_verify_buf,  1+4+sizeof(s_msg_version_t), 10);	

}

void MsgGetAllUserId(uint8_t count,uint8_t *userid,uint8_t result)
{
	s_msg_userid_reply_t useridinfo;

	uint8_t tmp_msg_enc[64];
	uint8_t msg_verify_buf[64];
	uint8_t size = 0;
	uint8_t checksum = 0;
	memset(&useridinfo,0,sizeof(s_msg_userid_reply_t));
	memset(tmp_msg_enc,0,64);
	memset(msg_verify_buf,0,64);
    //step 1: struct msg & encrypt
	useridinfo.MsgID = MID_REPLY;
	size = 3 + 2*count; 
	useridinfo.Size[0] = (size >> 8) & 0xff;
	useridinfo.Size[1] = size & 0xff;
	useridinfo.mid = MID_GETALLUSERID;
	useridinfo.result = result;

	useridinfo.data.user_counts = count > 20 ? 20 : count; 

	if(userid)
		memcpy(useridinfo.data.users_id,userid,2*useridinfo.data.user_counts);
	else
		memset(useridinfo.data.users_id,0,MAX_USER_COUNTS*2);

#if FOR_SENSETIME_DEBUG_DATA
	memcpy(tmp_msg_enc,&useridinfo,5+1+2*useridinfo.data.user_counts);
#else
	encBytes(&useridinfo,5+1+2*useridinfo.data.user_counts,encreleasekey.enc_release_key,16,tmp_msg_enc);
#endif

	checksum = msg_check_sum(tmp_msg_enc,5+1+2*useridinfo.data.user_counts);

    //step 2: struct verify reply msg
	msg_verify_buf[0] = (uint8_t)SYNC_WORD_FIRST;
	msg_verify_buf[1] = SYNC_WORD_SECOND;
	msg_verify_buf[2] = ((5+1+2*useridinfo.data.user_counts) >> 8) & 0xFF;
	msg_verify_buf[3] = (5+1+2*useridinfo.data.user_counts) & 0xFF;
	memcpy(&msg_verify_buf[4],tmp_msg_enc,5+1+2*useridinfo.data.user_counts);
	msg_verify_buf[4+5+1+2*useridinfo.data.user_counts]  = checksum;
    ifv_printf(IFV_MSG_DEBUG,"%s:", __func__);
	for(int i = 0; i< 1+4+5+1+2*useridinfo.data.user_counts;i++)
	{
		ifv_printf(IFV_MSG_DEBUG,"0x%02x,",msg_verify_buf[i]);
	}
	ifv_printf(IFV_MSG_DEBUG,"\n");
	hal_uart_send(&uart_ctrl, &msg_verify_buf,  1+4+5+1+2*useridinfo.data.user_counts, 10);	
}

void MsgGetUserInfoReply(uint16_t id, uint8_t* name,uint8_t admin,uint8_t result)
{
	s_msg_getuserinfo_t getuserinfo;
	uint8_t tmp_msg_enc[64];
	uint8_t msg_verify_buf[64];
	uint8_t checksum = 0;

	memset(&getuserinfo,0,sizeof(s_msg_getuserinfo_t));
	memset(tmp_msg_enc,0,64);
	memset(msg_verify_buf,0,64); 
    //step 1: struct msg & encrypt
	getuserinfo.MsgID = MID_REPLY;
	getuserinfo.Size[0] = (sizeof(s_msg_getuserinfo_t) >> 8) & 0xff;
	getuserinfo.Size[1] = sizeof(s_msg_getuserinfo_t) & 0xff;
	getuserinfo.mid = MID_GETUSERINFO;
	getuserinfo.result = result;
	getuserinfo.data.user_id_heb = (id >> 8) & 0xFF;
	getuserinfo.data.user_id_leb = id & 0xFF;
	getuserinfo.data.admin = admin;
	memcpy(getuserinfo.data.user_name,name,USER_NAME_SIZE);
#if FOR_SENSETIME_DEBUG_DATA
	memcpy(tmp_msg_enc,&getuserinfo,sizeof(s_msg_getuserinfo_t));
#else
	encBytes(&getuserinfo,sizeof(s_msg_getuserinfo_t),encreleasekey.enc_release_key,16,tmp_msg_enc);
#endif

	checksum = msg_check_sum(tmp_msg_enc,sizeof(s_msg_getuserinfo_t));
	
    //step 2: struct verify reply msg
	msg_verify_buf[0] = (uint8_t)SYNC_WORD_FIRST;
	msg_verify_buf[1] = SYNC_WORD_SECOND;
	msg_verify_buf[2] = (sizeof(s_msg_getuserinfo_t) >> 8) & 0xFF;
	msg_verify_buf[3] = (sizeof(s_msg_getuserinfo_t)) & 0xFF;
	memcpy(&msg_verify_buf[4],tmp_msg_enc,sizeof(s_msg_getuserinfo_t));
	msg_verify_buf[4+sizeof(s_msg_getuserinfo_t)]  = checksum;
	ifv_printf(IFV_MSG_DEBUG,"User Name:");
	for(int i = 0; i< 32 ; i++)
	{
		ifv_printf(IFV_MSG_DEBUG,"0x%02x,",getuserinfo.data.user_name[i]);
	}
	ifv_printf(IFV_MSG_DEBUG,"\n");
	ifv_printf(IFV_MSG_DEBUG,"User id =%d, admin=%d\n",(getuserinfo.data.user_id_heb<<8)|getuserinfo.data.user_id_leb, getuserinfo.data.admin);
	ifv_printf(IFV_MSG_DEBUG,"%s:", __func__);
	for(int i = 0; i< 1+4+sizeof(s_msg_getuserinfo_t);i++)
	{
		ifv_printf(IFV_MSG_DEBUG,"0x%02x,",msg_verify_buf[i]);
	}
	ifv_printf(IFV_MSG_DEBUG,"\n");
	hal_uart_send(&uart_ctrl, &msg_verify_buf,  1+4+sizeof(s_msg_getuserinfo_t), 10);	
}

void saveFeatureAck(uint32_t result,uint32_t id)
{
	uint8_t m2h_data[10];
	uint32_t tempID = 0;

	m2h_data[0] = MID_SAVE_FEARURE_UART;
	m2h_data[1] = result;
	if(0 == result)
	{
		dump_le_uint32((uint8_t *)&id,&tempID);
		memcpy(&m2h_data[2], &tempID, sizeof(uint32_t));
		m2h_msg_send(&uart_ctrl, MID_REPLY, 2 + sizeof(uint32_t), m2h_data);
	}
	else
		m2h_msg_send(&uart_ctrl, MID_REPLY, 2 + sizeof(uint32_t), m2h_data);
}


void registerFromUartAck(uint32_t result,uint32_t id)
{
	m2h_register_from_uart_ack(&uart_ctrl,result,id);
	//printf("[registerFromUartAck]:send ack done.id %d \n", id);

	isp_rgb_enable_flag = 1;
	aie_vis_detect_enable = 1;

	if(id != 0xffffffff)
		curRegisteredID = id;
}

void registerResultAck(int result,uint16_t id)
{
	uint8_t m2h_data[10];
	uint16_t tempID = 0;
	
	if(0 == result)
	{
		m2h_data[0] = MID_ENROLL;
		m2h_data[1] = MR_SUCCESS;
		dump_le_uint16((uint8_t *)&id,&tempID);
		memcpy(&m2h_data[2], &tempID, sizeof(uint16_t));
		m2h_msg_send(&uart_ctrl, MID_REPLY, 2+ sizeof(uint16_t), m2h_data);
	}
	else
	{
		m2h_data[0] = MID_ENROLL;
		m2h_data[1] = result;
		m2h_msg_send(&uart_ctrl, MID_REPLY, 2, m2h_data); 
	}
	//printf("[registerResultAck]:send ack done \n");
}

void multiAngleRegAck(uint8_t cmd, int result, uint16_t id, uint8_t direction)
{
	ifv_printf(IFV_MSG_DEBUG,"%s:", __func__);
	if(g_ifv_flow_cfg.sensetime_protocol_enable)
	{
		MsgEnrollReply(cmd, result, id, direction);
	}
	else
	{
		uint8_t m2h_data[10] = {0};
		uint16_t tempID = 0;

		m2h_data[0] = MID_ENROLL;
		m2h_data[1] = result;
		dump_le_uint16((uint8_t *)&id,&tempID);
		memcpy(&m2h_data[2], &tempID, sizeof(uint16_t));
		m2h_data[4] = direction;
		m2h_msg_send(&uart_ctrl, MID_REPLY, 2 + sizeof(uint16_t) + 1, m2h_data);
	}
}

void multiAngleRegNote(int result, int16_t left,int16_t top,int16_t right,int16_t bottom,int16_t yaw,int16_t pitch,int16_t roll)
{
	ifv_printf(IFV_MSG_INFO,"%s:state %d \n", __func__, result);
	MsgNoteFace(NID_FACE_STATE,result,left, top, right, bottom, yaw, pitch, roll);
}

void multiAngleRecogNote(int result, int16_t left,int16_t top,int16_t right,int16_t bottom,int16_t yaw,int16_t pitch,int16_t roll)
{
	ifv_printf(IFV_MSG_INFO,"%s:state %d \n", __func__, result);
	MsgNoteFace(NID_FACE_STATE,result,left, top, right, bottom, yaw, pitch, roll);
}

void recognizeResultAck(int result,uint16_t id)
{
	uint8_t m2h_data[10];
	uint16_t tempID = 0;

	if(0 == result)
	{
		m2h_data[0] = MID_VERIFY;
		m2h_data[1] = MR_SUCCESS;
		dump_le_uint16((uint8_t *)&id,&tempID);
		memcpy(&m2h_data[2], &tempID, sizeof(uint16_t));
		m2h_msg_send(&uart_ctrl, MID_REPLY, 2+ sizeof(uint16_t), m2h_data);
	}
	else
	{
		m2h_data[0] = MID_VERIFY;
		m2h_data[1] = result;
		m2h_msg_send(&uart_ctrl, MID_REPLY, 2, m2h_data); 
	}

	ifv_printf(IFV_MSG_DEBUG,"%s:send done \n", __func__);
}

void multiAngleRecogAck(int result, uint16_t id, uint8_t *name, uint8_t admin, uint8_t eyeStatus)
{
	ifv_printf(IFV_MSG_DEBUG,"%s \n", __func__);
	if(g_ifv_flow_cfg.sensetime_protocol_enable)
	{
		if(result == MR_SUCCESS)	
		{
			int i = 0;
			ifv_printf(IFV_MSG_DEBUG,"username:");
			for(i = 0;i <32; i++)
			{
				ifv_printf(IFV_MSG_DEBUG,"%02x ",name[i]);
			}
			ifv_printf(IFV_MSG_DEBUG,"\n");
			ifv_printf(IFV_MSG_DEBUG,"admin :%d, id:%d, eyeStatus:%d\n",admin, id, eyeStatus);
			MsgVeifyReply(result,id,name,admin,eyeStatus);
		}
		else
		{
			MsgVeifyUnSuccessReply(result);
		}
	}
	else
	{
		uint8_t m2h_data[40] = {0};
		s_msg_reply_verify_data *reply_data = NULL;

		m2h_data[0] = MID_VERIFY;
		m2h_data[1] = result;

		reply_data = (s_msg_reply_verify_data *)(&m2h_data[2]);
		memset(reply_data, 0, sizeof(s_msg_reply_verify_data));
		reply_data->user_id_heb = 0;
		reply_data->user_id_leb = id;
		reply_data->admin = admin;
		reply_data->unlockStatus = eyeStatus;
		memcpy(reply_data->user_name, name, USER_NAME_SIZE);
		
		m2h_msg_send(&uart_ctrl, MID_REPLY, 2 + sizeof(s_msg_reply_verify_data), m2h_data);	
	}
}


void delUserResultAck(uint32_t flag,int result,uint16_t id)
{
	ifv_printf(IFV_MSG_DEBUG,"%s, flag %d, id %d \n", __func__, flag, id);

	if(g_ifv_flow_cfg.sensetime_protocol_enable){
		if(FLAG_DEL_USER_RANGE == flag)
			MsgNoDataReply(MID_DELUSER_RANG,result);
		else if(FLAG_DEL_USER_NORMAL == flag)
			MsgNoDataReply(MID_DELUSER,result);
	}
	else{
		uint8_t m2h_data[10];
	
		if(0 == result)
		{
			m2h_data[0] = MID_DELUSER;
			m2h_data[1] = MR_SUCCESS;
			m2h_msg_send(&uart_ctrl, MID_REPLY, 2, m2h_data);
		}
		else
		{
			m2h_data[0] = MID_DELUSER;
			m2h_data[1] = MR_FAILED4_TIMEOUT;
			m2h_msg_send(&uart_ctrl, MID_REPLY, 2, m2h_data); 
		}
	}
	ifv_printf(IFV_MSG_DEBUG,"%s:send ack done \n", __func__);
}

void delAllResultAck(int result)
{
	ifv_printf(IFV_MSG_DEBUG,"%s \n", __func__);
	if(g_ifv_flow_cfg.sensetime_protocol_enable)
	{
		MsgNoDataReply(MID_DELALL,result);
	}
	else{
		uint8_t m2h_data[10];
	
		if(0 == result)
		{
			m2h_data[0] = MID_DELALL;
			m2h_data[1] = MR_SUCCESS;
			m2h_msg_send(&uart_ctrl, MID_REPLY, 2, m2h_data);
		}
		else
		{
			m2h_data[0] = MID_DELALL;
			m2h_data[1] = MR_FAILED4_TIMEOUT;
			m2h_msg_send(&uart_ctrl, MID_REPLY, 2, m2h_data); 
		}
		//printf("[delAllResultAck]:send ack done \n");
	}
}

void cmdAnalysisErrAck(void)
{
	if(g_ifv_flow_cfg.sensetime_protocol_enable){
		systemUnknowErrorNoteMsg();
	}else{
		hal_uart_send(&uart_ctrl, cmd_err_ack, sizeof(cmd_err_ack), 10);
	}	
}

void resetAck(void)
{
	MsgNoDataReply(MID_RESET,MR_SUCCESS);
//	hal_uart_send(&uart_ctrl, cmd_reset_ack, sizeof(cmd_err_ack), 10);
}

void faceResetAck(void)
{
	MsgNoDataReply(MID_FACERESET,MR_SUCCESS);
//	hal_uart_send(&uart_ctrl, cmd_face_reset_ack, sizeof(cmd_err_ack), 10);
}

void getCurrentRegisteredID(void)
{
	m2h_request_id_ack(&uart_ctrl,curRegisteredID);
	//printf("[getCurrentRegisteredID]:send ack done .id %d \n",curRegisteredID);
}

void getEveryModelVersion(char *version, char *detect, char *landmark, char *recog)
{
	if(NULL == version) 
		return;
	
	int i = 0;
	int strLen = strlen(version);
	int curLen = 0;
	int count = 0;
	printf("len %d, %s \n", strLen, version);
	for(i=0;i<strLen;i++)
	{
		//printf("char %d %c, %02x \n", i, version[i], version[i]);
		curLen++;
		if(',' == version[i])
		{
			if(0 == count){
				memcpy(detect, &version[0], curLen-1);
				//printf("detect:%s %d \n", detect, strlen(detect));
			}	
			else if(1 == count)
			{
				memcpy(landmark, &version[strlen(detect)+2], curLen-2);
				//printf("landmark:%s %d \n", landmark, strlen(landmark));
			}

			count++;
			curLen = 0;
		} 
	}
	
	if(2 == count)
		memcpy(recog, &version[strlen(detect)+strlen(landmark)+4], strLen-strlen(detect)-strlen(landmark)-4);

	printf("start %s : %d end\n", detect, strlen(detect));
	printf("start %s : %d end\n", landmark, strlen(landmark));
	printf("start %s : %d end\n", recog, strlen(recog));
}

void getModleVersionAck(char *detect, char *landmark ,char *recog)
{
	int ret = 0;
	if((NULL == detect) || (NULL == landmark) || (NULL == recog))
	{
		ret = 1;
	}

	uint8_t m2h_data[70] = {0};
	m2h_data[0] = MID_GET_MODLE_VERSION;
	
	if(0 == ret){
		m2h_data[1] = MR_SUCCESS;
		memcpy(&m2h_data[2], detect, strlen(detect));
		memcpy(&m2h_data[2+MODLE_VERSION_MAX_LEN], landmark, strlen(landmark));
		memcpy(&m2h_data[2+MODLE_VERSION_MAX_LEN+MODLE_VERSION_MAX_LEN], recog, strlen(recog));
		m2h_msg_send(&uart_ctrl, MID_REPLY, MODLE_VERSION_MAX_LEN*3+2, m2h_data);
	}
	else
	{
		m2h_data[1] = ret;
		m2h_msg_send(&uart_ctrl, MID_REPLY, 2, m2h_data); 
	}
}

static int uart_init(void)
{

	#if 0
    drv_pinmux_config(OTP_MUX,UART1_MUX);
	drv_enable_uart_clock(COMM_UART_IDX);
	uart_ctrl.hard                = UART_HARD_UART;
	uart_ctrl.port                = COMM_UART_IDX;   // COMM_UART_IDX = 1
	#else
	uart_ctrl.hard = COMM_USART_MODE;
	uart_ctrl.port                = COMM_USART_IDX;
	#endif

    uart_ctrl.config.baud_rate    = 115200;
    uart_ctrl.config.data_width   = DATA_WIDTH_8BIT;
    uart_ctrl.config.parity       = NO_PARITY;
    uart_ctrl.config.stop_bits    = STOP_BITS_1;
    uart_ctrl.config.flow_control = FLOW_CONTROL_DISABLED;
	
    return hal_uart_init(&uart_ctrl);
}

int comm_uart_init(void)
{
	if(uart_init()!=0)
	{
		LOGE(TAG,"uart%d init failed!\n", COMM_USART_IDX);
	}
	uart_recv_buf = aos_malloc(UART_RECV_BUF_SIZE);
	if(uart_recv_buf == NULL)
		return -1;
	memset(uart_recv_buf, 0, UART_RECV_BUF_SIZE);
	
	LOGI(TAG, "uart_task_init success! \n");
	return 0;
}


void uart_task(void *paras)
{	
	int ret;
	const char *task_name = aos_task_name();
	LOGI(TAG,"%s start!\r\n", task_name);
	
	//hal_uart_send(&uart_ctrl, power_on_ready, sizeof(power_on_ready), 10);
	systemReadyNoteMsg();
	if(g_ifv_flow_cfg.sensetime_protocol_enable)
	{
		int key_len = 16;
		int mode_len = 1;
		int mode = 0xFF;
		msg_getValueKV(MSG_ENCRYT_KEY, encreleasekey.enc_release_key, &key_len);
		msg_getValueKV(MSG_ENCRYT_KEY_NUM, enckeynumber.enc_key_number, &key_len);
		
		msg_getValueKV(MSG_ENCRYT_MODE, &mode, &mode_len);
		ifv_printf(IFV_MSG_DEBUG,"Get KEY: ");
		for(int i =0; i<16;i++)
		{
			ifv_printf(IFV_MSG_DEBUG,"%02x ",encreleasekey.enc_release_key[i]);
		}
		ifv_printf(IFV_MSG_DEBUG,"\n");
		ifv_printf(IFV_MSG_DEBUG,"Get KEY NUM: ");
		for(int i =0; i<16;i++)
		{
			ifv_printf(IFV_MSG_DEBUG,"%02x ",enckeynumber.enc_key_number[i]);
		}
		ifv_printf(IFV_MSG_DEBUG,"\n");
		ifv_printf(IFV_MSG_DEBUG,"Get Encrypt Mode: %d\n",mode);

		if((encreleasekey.enc_release_key == NULL) || (key_len != 16))
		{
			ifv_printf(IFV_MSG_WARNING,"please init encry! \n");
		}
	}
	
    while(1) 
	{
		int rece_size =0;

		ret = h2m_msg_recv(&uart_ctrl, uart_recv_buf, &rece_size);
		if(rece_size > 0)
		{
			handle_host_cmd(uart_recv_buf);
		}

		if(5 == ret)
		{
			if(1 == enroll_from_uart_busy_flag)
			{
				printf("read data failed ,ret %d \n", ret);
				registerFromUartAck(1,0xffffffff);
			}
			else
			{
				cmdAnalysisErrAck();
			}
		}

        aos_msleep(1);
    }
}
